package guda.house.biz.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import guda.grape.util.Convert;
import guda.house.biz.beans.vo.PayDetail;
import guda.house.biz.beans.vo.PayDetailVO;
import guda.house.biz.constants.CommonResultCode;
import guda.house.biz.enums.WxPayStatusEnum;
import guda.house.biz.query.*;
import guda.house.biz.security.AuthUser;
import guda.house.biz.util.DateUtil;
import guda.house.biz.util.PriceUtil;
import guda.house.biz.util.Transform;
import guda.house.biz.util.TransformHelper;
import guda.house.dal.dao.*;
import guda.house.dal.dataobject.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import guda.house.biz.WxPayOrderBiz;
import guda.grape.autogen.common.page.BaseQuery;
import guda.grape.autogen.common.page.BizResult;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class WxPayOrderBizImpl implements WxPayOrderBiz{

    private final static Logger logger = LoggerFactory.getLogger(WxPayOrderBizImpl.class);

    @Autowired
    private WxPayOrderDAO wxPayOrderDAO;
    @Autowired
    private WxPayDetailDAO wxPayDetailDAO;
    @Autowired
    private WxAccessDAO wxAccessDAO;
    @Autowired
    private WxSuiteRelDAO wxSuiteRelDAO;
    @Autowired
    private BillEstateDAO billEstateDAO;
    @Autowired
    private BillElecDAO billElecDAO;
    @Autowired
    private BillWaterDAO billWaterDAO;
    @Autowired
    private BillParkingDAO billParkingDAO;
    @Autowired
    private SuiteDAO suiteDAO;
    @Autowired
    private UnitDAO unitDAO;
    @Autowired
    private BuildingDAO buildingDAO;
    @Autowired
    private VillageDAO villageDAO;
    @Autowired
    private OwnerDAO ownerDAO;
    @Autowired
    private BillPayDAO billPayDAO;
    @Autowired
    private BillExtDAO billExtDAO;
    @Autowired
    private TransactionTemplate transactionTemplate;

    public BizResult detail(long id) {
        BizResult bizResult = new BizResult();
        try{
            WxPayOrderDO wxPayOrderDO = wxPayOrderDAO.getWxPayOrderById(id);
            bizResult.data.put("wxPayOrderDO", wxPayOrderDO);
            bizResult.success = true;
        }catch(Exception e){
            logger.error("query WxPayOrder error",e);
        }
        return bizResult;
}

    public BizResult list(BaseQuery baseQuery) {
        BizResult bizResult = new BizResult();
        try {
            int totalCount = wxPayOrderDAO.countForPage(baseQuery);
            baseQuery.setTotalCount(totalCount);
            List<WxPayOrderDO> wxPayOrderList = wxPayOrderDAO.selectForPage(baseQuery);
            bizResult.data.put("wxPayOrderList", wxPayOrderList);
            bizResult.data.put("query", baseQuery);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("view WxPayOrder list error", e);
        }
            return bizResult;
     }

    public BizResult delete(long id) {
        BizResult bizResult = new BizResult();
        try {
            wxPayOrderDAO.delWxPayOrderById(id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("delete wxPayOrder error", e);
        }
        return bizResult;
    }

    public BizResult create(WxPayOrderDO wxPayOrderDO) {
        BizResult bizResult = new BizResult();
        try {
            long id = wxPayOrderDAO.insert(wxPayOrderDO);
            bizResult.data.put("id", id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("create WxPayOrder error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult update(WxPayOrderDO wxPayOrderDO) {
        BizResult bizResult = new BizResult();
        try {
            wxPayOrderDAO.updateByIdSelective(wxPayOrderDO);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("update WxPayOrder error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult prepareForPay(Long suiteId) {
        BizResult bizResult = new BizResult();
        Long accessId = AuthUser.getCurrentUser().getUserId();
        WxAccessDO wxAccessById = wxAccessDAO.getWxAccessById(accessId);
        if(wxAccessById == null){
            bizResult.code= CommonResultCode.PERM_ERROR;
            return bizResult;
        }
        final PayDetailVO payDetailVO = getPayDetail(suiteId);
        if(payDetailVO == null){
            bizResult.code=CommonResultCode.UNKOWN_ERROR;
            return bizResult;
        }
        bizResult.data.put("wxAccessById",wxAccessById);
        bizResult.data.put("suiteName",getSuiteName(suiteId));
        bizResult.data.put("payDetailVO", payDetailVO);
        final WxPayOrderDO wxPayOrderDO = new WxPayOrderDO();
        wxPayOrderDO.setOpenid(wxAccessById.getOpenid());
        wxPayOrderDO.setUnionid(wxAccessById.getUnionid());
        wxPayOrderDO.setSuiteId(suiteId);
        wxPayOrderDO.setPayTotal(payDetailVO.getPayTotal());
        wxPayOrderDO.setOrderNo(FrontFeeBizImpl.OrderNoHelper.next(1l));
        StringBuilder buf = new StringBuilder();
        for(PayDetail payDetail:payDetailVO.getPayDetailList()){
            buf.append(payDetail.getFeeName()).append("(").append(DateUtil.formatYMD(payDetail.getStart()))
                    .append("-").append(DateUtil.formatYMD(payDetail.getEnd())).append(")金额：")
            .append(PriceUtil.formatCNY(payDetail.getPayTotal())).append("元;");
        }
        wxPayOrderDO.setOrderContent(buf.toString());
        wxPayOrderDO.setPayStatus(WxPayStatusEnum.init.getVal());
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                Long insert = wxPayOrderDAO.insert(wxPayOrderDO);
                for (PayDetail payDetail : payDetailVO.getPayDetailList()) {
                    for (String s : payDetail.getBillIdList()) {
                        String[] split = s.split("_");
                        WxPayDetailDO wxPayDetailDO = new WxPayDetailDO();
                        wxPayDetailDO.setOrderId(insert);
                        wxPayDetailDO.setBillId(Convert.toLong(split[1]));
                        wxPayDetailDO.setBillType(split[0]);
                        wxPayDetailDAO.insert(wxPayDetailDO);
                    }
                }
            }
        });
        bizResult.data.put("wxPayOrderDO", wxPayOrderDO);
        bizResult.success=true;
        return bizResult;
    }

    private String getSuiteName(Long suiteId){
        SuiteDO suiteById = suiteDAO.getSuiteById(suiteId);
        UnitDO unitById = unitDAO.getUnitById(suiteById.getUnitId());
        BuildingDO buildingById = buildingDAO.getBuildingById(unitById.getBuildingId());
        VillageDO villageById = villageDAO.getVillageById(buildingById.getVillageId());
        return villageById.getVillageName()+buildingById.getBuildingName()+"(幢)"+unitById.getUnitName()+"(单元)"+suiteById.getSuiteName()+"(房号)";
    }

    private PayDetailVO getPayDetail(Long suiteId){
        List<BillElecDO> billElecDOList = new ArrayList<BillElecDO>();
        List<BillWaterDO> billWaterDOList = new ArrayList<BillWaterDO>();
        List<BillEstateDO> billEstateDOList = new ArrayList<BillEstateDO>();
        List<BillParkingDO> billParkingDOList = new ArrayList<BillParkingDO>();

        BillParkingQuery billParkingQuery = new BillParkingQuery();
        billParkingQuery.setPageSize(500);
        billParkingQuery.setSuiteId(suiteId);
        billParkingDOList = billParkingDAO.selectForUnpay(billParkingQuery);

        BillEstateQuery billEstateQuery = new BillEstateQuery();
        billEstateQuery.setPageSize(500);
        billEstateQuery.setSuiteId(suiteId);
        billEstateDOList = billEstateDAO.selectForUnpay(billEstateQuery);

        BillWaterQuery billWaterQuery = new BillWaterQuery();
        billWaterQuery.setPageSize(500);
        billWaterQuery.setSuiteId(suiteId);
        billWaterDOList = billWaterDAO.selectForUnpay(billWaterQuery);

        BillElecQuery billElecQuery = new BillElecQuery();
        billElecQuery.setPageSize(500);
        billElecQuery.setSuiteId(suiteId);
        billElecDOList = billElecDAO.selectForUnpay(billElecQuery);



        long allTotal = 0L;
        PayDetailVO payDetailVO = new PayDetailVO();
        List<PayDetail> payDetailList = new ArrayList<PayDetail>();
        payDetailVO.setPayDetailList(payDetailList);
        if (billEstateDOList.size() > 0) {
            Collections.sort(billEstateDOList, new Comparator<BillEstateDO>() {
                @Override
                public int compare(BillEstateDO o1, BillEstateDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("物业费");
            payDetail.setStart(billEstateDOList.get(billEstateDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billEstateDOList.get(0).getGmtEnd());
            List<String> billId = TransformHelper.transform(billEstateDOList, new Transform<BillEstateDO, String>() {
                @Override
                public String transform(BillEstateDO object) {
                    return "estate_" + object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillEstateDO billEstateDO1 : billEstateDOList) {
                c = c + billEstateDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }

        if (billWaterDOList.size() > 0) {
            Collections.sort(billWaterDOList, new Comparator<BillWaterDO>() {
                @Override
                public int compare(BillWaterDO o1, BillWaterDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });

            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("水费");
            payDetail.setStart(billWaterDOList.get(billWaterDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billWaterDOList.get(0).getGmtEnd());
            List<String> billId = TransformHelper.transform(billWaterDOList, new Transform<BillWaterDO, String>() {
                @Override
                public String transform(BillWaterDO object) {
                    return "water_" + object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillWaterDO billWaterDO1 : billWaterDOList) {
                c = c + billWaterDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }

        if (billElecDOList.size() > 0) {
            Collections.sort(billElecDOList, new Comparator<BillElecDO>() {
                @Override
                public int compare(BillElecDO o1, BillElecDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });

            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("电费");
            payDetail.setStart(billElecDOList.get(billElecDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billElecDOList.get(0).getGmtEnd());
            List<String> billId = TransformHelper.transform(billElecDOList, new Transform<BillElecDO, String>() {
                @Override
                public String transform(BillElecDO object) {
                    return "elec_" + object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillElecDO billElecDO1 : billElecDOList) {
                c = c + billElecDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();
        }
        if (billParkingDOList.size() > 0) {
            Collections.sort(billParkingDOList, new Comparator<BillParkingDO>() {
                @Override
                public int compare(BillParkingDO o1, BillParkingDO o2) {
                    return o2.getGmtStart().compareTo(o1.getGmtStart());
                }
            });
            PayDetail payDetail = new PayDetail();
            payDetail.setFeeName("车位费");
            payDetail.setStart(billParkingDOList.get(billParkingDOList.size() - 1).getGmtStart());
            payDetail.setEnd(billParkingDOList.get(0).getGmtEnd());
            List<String> billId = TransformHelper.transform(billParkingDOList, new Transform<BillParkingDO, String>() {
                @Override
                public String transform(BillParkingDO object) {
                    return "parking_" + object.getBillId();
                }
            });
            payDetail.setBillIdList(billId);

            long c = 0L;
            for (BillParkingDO billParkingDO1 : billParkingDOList) {
                c = c + billParkingDO1.getPayTotal();
            }
            payDetail.setPayTotal(c);
            payDetailList.add(payDetail);
            allTotal = allTotal + payDetail.getPayTotal();

        }
        if(payDetailList.size() ==0){
            return null;
        }
        payDetailVO.setPayTotal(allTotal);
        payDetailVO.setPayTotalCN(PriceUtil.toRMB(allTotal));
        return payDetailVO;
    }


}
